#ifndef RoAbstractComponent__h
#define RoAbstractComponent__h


#include <QtCore>

#include "RoStanzas.h"

class RoAbstractModule;
class RoQuery;


class RoAbstractComponent:
    public QObject
{
    Q_OBJECT

    Q_ENUMS(RoMethodResult);

    Q_PROPERTY( QString name
                READ name
                WRITE setName )

public:
    
    typedef QObject super;

    enum RoMethodResult
    {
        NotFinishedYet,
        FinishedSuccessfully,
        FinishedWithError
    };

    RoAbstractComponent(RoAbstractModule * parent = 0);

    RoAbstractModule * parentModule() const;

    QString name() const
    {
        return objectName();
    }

    void setName(QString name);

    /// Вызов некого ромашкового метода (кто-то вызывает нас).
    /// Мы попадаем сюда при вызове любого метода.
    /// @param[in] stanza  должна быть <iq type=request/>
    virtual void query_in_start(RoIqStanza stanza);

    /// Приход порции данных к запросу метода (чьего-то, вызванного нами).
    /// @param[in] stanza  должна быть <iq type=datum/>
    void query_out_datum(RoIqStanza stanza);

    /// Завершение вызванного ранее ромашкового метода (чьего-то, вызванного нами).
    /// @param[in] stanza  должна быть <iq type=(result|error)/>
    void query_out_end(RoIqStanza stanza);

    void recieve_own_stanza(RoStanza stanza);

    virtual void receive_stanza_error(RoErrorStanza stanza);

    virtual void receive_stanza_info(RoInfoStanza stanza);

    void receive_stanza_iq(RoIqStanza stanza);

    RoQuery * createSimpleQuery(QString remoteComponentName, QString remoteMethod);

public slots:

    /// Послать строфу в сеть.
    RoStanzaId sendStanza(RoStanza stanza);

    RoMethodResult ro_query_interface(RoIqStanza request, QDomDocument * answer);

protected:

    /// Первый ключ — ромашкофицированное имя метода.
    /// Второй ключ — description или example, см. документацию по методу query-interface.
    QMap<QString, QMap<QString, QString> > methods;

private:

    QMap<RoStanzaId, RoQuery*> activeQueries;

    /// Проверка сигнатур ромашковых методов
    Q_INVOKABLE void checkRoMethods();

private slots:

    void addActiveQuery(RoStanzaId rid);

    void closeLornQueries(const QString & goneComponent);

}; // class RoAbstractComponent


#endif // RoAbstractComponent__h
